#include "ipc_server.h"

#include <gio/gio.h>
#include <thread>
#include <mutex>

// (非框架设计者不用理会这里的任何内容)

/**
用法:
	1. 实现IServiceController，创建对应的对象
	2. 实现IServiceControllerFactory, 根据serviceName返回IServiceController
	3. 调用Server::setServiceControllerFactory
	4. 调用一次或者多次Server::newService创建若干服务
*/
namespace ipc
{
	// 提前声明创建GDBUS服务的函数
	static void prvNewService(const std::string& serviceName);	
	static void prvUpdate(Bundle& data);
	static void prvUpdate(const void* connection, const std::string& id, int64_t observerId, Bundle& data);

	// 服务控制器工厂
	IServiceControllerFactory* sFactory = nullptr;
	
	Server* Server::getInstance()
	{
		static Server* instance = new Server();
		return instance;
	}
	
	// 设置服务器工厂
	void Server::setServiceControllerFactory(IServiceControllerFactory* factory)
	{
		sFactory = factory;
	}	
	
	// 创建服务
	void Server::newService(std::string serviceName)
	{
		prvNewService(serviceName);
	}
	
	void Server::update(Bundle& data)
	{
		prvUpdate(data);
	}
	
	void Server::update(const void* connection, const std::string& id, int64_t observerId, Bundle& data)
	{
		prvUpdate(connection, id, observerId, data);
	}
	
}	// namespace ipc
	
	
	
	
namespace ipc
{
	// 减少函数调用
	static const std::string& KEY_ID 		= IpcKit::getKeyId();
	static const std::string& KEY_VALUE		= IpcKit::getKeyValue();
	static const std::string& KEY_OBSERVER	= IpcKit::getKeyObserver();
	
	// 回调基本类型给和id关联的通道 -----------------------------------------------------------------------------
	
	void Server::updateInt8(const std::string& id, int8_t value)
	{
		prvUpdate(Bundle().setString(KEY_ID, id).setInt8(KEY_VALUE, value));
	}
	
	void Server::updateInt16(const std::string& id, int16_t value)
	{
		prvUpdate(Bundle().setString(KEY_ID, id).setInt16(KEY_VALUE, value));
	}
	
	void Server::updateInt32(const std::string& id, int32_t value)
	{
		prvUpdate(Bundle().setString(KEY_ID, id).setInt32(KEY_VALUE, value));
	}
	
	void Server::updateInt64(const std::string& id, int64_t value)
	{
		prvUpdate(Bundle().setString(KEY_ID, id).setInt64(KEY_VALUE, value));
	}
	
	void Server::updateFloat(const std::string& id, float value)
	{
		prvUpdate(Bundle().setString(KEY_ID, id).setFloat(KEY_VALUE, value));
	}
	
	void Server::updateDouble(const std::string& id, double value)
	{
		prvUpdate(Bundle().setString(KEY_ID, id).setDouble(KEY_VALUE, value));
	}
	
	void Server::updateString(const std::string& id, const std::string& value)
	{
		prvUpdate(Bundle().setString(KEY_ID, id).setString(KEY_VALUE, value));
	}
		
	// 回调基本类型数组给和id关联的通道 -----------------------------------------------------------------------------
	
	void Server::updateInt8Vector(const std::string& id, const std::vector<int8_t>& value)
	{
		prvUpdate(Bundle().setString(KEY_ID, id).setInt8Vector(KEY_VALUE, value));
	}
	
	void Server::updateInt16Vector(const std::string& id, const std::vector<int16_t>& value)
	{
		prvUpdate(Bundle().setString(KEY_ID, id).setInt16Vector(KEY_VALUE, value));
	}
	
	void Server::updateInt32Vector(const std::string& id, const std::vector<int32_t>& value)
	{
		prvUpdate(Bundle().setString(KEY_ID, id).setInt32Vector(KEY_VALUE, value));
	}
	
	void Server::updateInt64Vector(const std::string& id, const std::vector<int64_t>& value)
	{
		prvUpdate(Bundle().setString(KEY_ID, id).setInt64Vector(KEY_VALUE, value));
	}
	
	void Server::updateFloatVector(const std::string& id, const std::vector<float>& value)
	{
		prvUpdate(Bundle().setString(KEY_ID, id).setFloatVector(KEY_VALUE, value));
	}
	
	void Server::updateDoubleVector(const std::string& id, const std::vector<double>& value)
	{
		prvUpdate(Bundle().setString(KEY_ID, id).setDoubleVector(KEY_VALUE, value));
	}
	
	void Server::updateStringVector(const std::string& id, const std::vector<std::string>& value)
	{
		prvUpdate(Bundle().setString(KEY_ID, id).setStringVector(KEY_VALUE, value));
	}
	
	// 回调基本类型数组给和id关联的通道(右值版本, 防止大规模变量拷贝) -----------------------------------------------------------------------------
	
	void Server::updateInt8Vector(const std::string& id, std::vector<int8_t>&& value)
	{
		prvUpdate(Bundle().setString(KEY_ID, id).setInt8Vector(KEY_VALUE, std::move(value)));
	}
	
	void Server::updateInt16Vector(const std::string& id, std::vector<int16_t>&& value)
	{
		prvUpdate(Bundle().setString(KEY_ID, id).setInt16Vector(KEY_VALUE, std::move(value)));
	}
	
	void Server::updateInt32Vector(const std::string& id, std::vector<int32_t>&& value)
	{
		prvUpdate(Bundle().setString(KEY_ID, id).setInt32Vector(KEY_VALUE, std::move(value)));
	}
	
	void Server::updateInt64Vector(const std::string& id, std::vector<int64_t>&& value)
	{
		prvUpdate(Bundle().setString(KEY_ID, id).setInt64Vector(KEY_VALUE, std::move(value)));
	}
	
	void Server::updateFloatVector(const std::string& id, std::vector<float>&& value)
	{
		prvUpdate(Bundle().setString(KEY_ID, id).setFloatVector(KEY_VALUE, std::move(value)));
	}
	
	void Server::updateDoubleVector(const std::string& id, std::vector<double>&& value)
	{
		prvUpdate(Bundle().setString(KEY_ID, id).setDoubleVector(KEY_VALUE, std::move(value)));
	}
	
	void Server::updateStringVector(const std::string& id, std::vector<std::string>&& value)
	{
		prvUpdate(Bundle().setString(KEY_ID, id).setStringVector(KEY_VALUE, std::move(value)));
	}
	
	
	// 回调基本类型给指定通道(通常在是IServiceController::handleUpdate中调用) -----------------------------------------------------------------------------
	
	void Server::updateInt8(const void* connection, const std::string& id, int64_t observerId, int8_t value)
	{
		prvUpdate(connection, id, observerId, Bundle().setInt8(KEY_VALUE, value));
	}
	
	void Server::updateInt16(const void* connection, const std::string& id, int64_t observerId, int16_t value)
	{
		prvUpdate(connection, id, observerId, Bundle().setInt16(KEY_VALUE, value));
	}
	
	void Server::updateInt32(const void* connection, const std::string& id, int64_t observerId, int32_t value)
	{
		prvUpdate(connection, id, observerId, Bundle().setInt32(KEY_VALUE, value));
	}
	
	void Server::updateInt64(const void* connection, const std::string& id, int64_t observerId, int64_t value)
	{
		prvUpdate(connection, id, observerId, Bundle().setInt64(KEY_VALUE, value));
	}
	
	void Server::updateFloat(const void* connection, const std::string& id, int64_t observerId, float value)
	{
		prvUpdate(connection, id, observerId, Bundle().setFloat(KEY_VALUE, value));
	}
	
	void Server::updateDouble(const void* connection, const std::string& id, int64_t observerId, double value)
	{
		prvUpdate(connection, id, observerId, Bundle().setDouble(KEY_VALUE, value));
	}
	
	void Server::updateString(const void* connection, const std::string& id, int64_t observerId, std::string value)
	{
		prvUpdate(connection, id, observerId, Bundle().setString(KEY_VALUE, value));
	}
	
	
	// 回调基本类型数组给指定通道(通常在是IServiceController::handleUpdate中调用) -----------------------------------------------------------------------------
	
	void Server::updateInt8Vector(const void* connection, const std::string& id, int64_t observerId, const std::vector<int8_t>& value)
	{
		prvUpdate(connection, id, observerId, Bundle().setInt8Vector(KEY_VALUE, value));
	}
	
	void Server::updateInt16Vector(const void* connection, const std::string& id, int64_t observerId, const std::vector<int16_t>& value)
	{
		prvUpdate(connection, id, observerId, Bundle().setInt16Vector(KEY_VALUE, value));
	}
	
	void Server::updateInt32Vector(const void* connection, const std::string& id, int64_t observerId, const std::vector<int32_t>& value)
	{
		prvUpdate(connection, id, observerId, Bundle().setInt32Vector(KEY_VALUE, value));
	}
	
	void Server::updateInt64Vector(const void* connection, const std::string& id, int64_t observerId, const std::vector<int64_t>& value)
	{
		prvUpdate(connection, id, observerId, Bundle().setInt64Vector(KEY_VALUE, value));
	}
	
	void Server::updateFloatVector(const void* connection, const std::string& id, int64_t observerId, const std::vector<float>& value)
	{
		prvUpdate(connection, id, observerId, Bundle().setFloatVector(KEY_VALUE, value));
	}
	
	void Server::updateDoubleVector(const void* connection, const std::string& id, int64_t observerId, const std::vector<double>& value)
	{
		prvUpdate(connection, id, observerId, Bundle().setDoubleVector(KEY_VALUE, value));
	}
	
	void Server::updateStringVector(const void* connection, const std::string& id, int64_t observerId, const std::vector<std::string>& value)
	{
		prvUpdate(connection, id, observerId, Bundle().setStringVector(KEY_VALUE, value));
	}
	
	
	// 回调基本类型数组给指定通道(通常在是IServiceController::handleUpdate中调用)(右值版本, 防止大规模变量拷贝) -----------------------------------------------------------------------------
	
	void Server::updateInt8Vector(const void* connection, const std::string& id, int64_t observerId, std::vector<int8_t>&& value)
	{
		prvUpdate(connection, id, observerId, Bundle().setInt8Vector(KEY_VALUE, std::move(value)));
	}
	
	void Server::updateInt16Vector(const void* connection, const std::string& id, int64_t observerId, std::vector<int16_t>&& value)
	{
		prvUpdate(connection, id, observerId, Bundle().setInt16Vector(KEY_VALUE, std::move(value)));
	}
	
	void Server::updateInt32Vector(const void* connection, const std::string& id, int64_t observerId, std::vector<int32_t>&& value)
	{
		prvUpdate(connection, id, observerId, Bundle().setInt32Vector(KEY_VALUE, std::move(value)));
	}
	
	void Server::updateInt64Vector(const void* connection, const std::string& id, int64_t observerId, std::vector<int64_t>&& value)
	{
		prvUpdate(connection, id, observerId, Bundle().setInt64Vector(KEY_VALUE, std::move(value)));
	}
	
	void Server::updateFloatVector(const void* connection, const std::string& id, int64_t observerId, std::vector<float>&& value)
	{
		prvUpdate(connection, id, observerId, Bundle().setFloatVector(KEY_VALUE, std::move(value)));
	}
	
	void Server::updateDoubleVector(const void* connection, const std::string& id, int64_t observerId, std::vector<double>&& value)
	{
		prvUpdate(connection, id, observerId, Bundle().setDoubleVector(KEY_VALUE, std::move(value)));
	}
	
	void Server::updateStringVector(const void* connection, const std::string& id, int64_t observerId, std::vector<std::string>&& value)
	{
		prvUpdate(connection, id, observerId, Bundle().setStringVector(KEY_VALUE, std::move(value)));
	}
}	// namespace ipc

	
	
	
	
	
	
	
// ------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------
// GDBUS相关 (prv前缀代表private, 是私有的意思, 模仿FreeRTOS)
// 这里以后可能会换成Binder
// ------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------	
namespace ipc
{		
	static std::map<GDBusConnection*, std::set<std::string>> sConnectionToIdsMap;
	static std::map<std::string, std::set<GDBusConnection*>> sIdToConnectionsMap;
	static std::mutex sMapMutex;
	
	// 对象转换 ---------------------------------------------
	
	// 删除Parcel对象
	static void prvDeleteParcel(gpointer data)
	{
		delete ((Parcel*)data);
	}
	
	// 对象转换
	static GVariant* prvToGVariant(const Bundle& bundle)
	{
		// 序列化
		Parcel *parcel = new Parcel;
		bundle.writeToParcel(parcel);
		
		// 创建对象
		return g_variant_new("(@ay)", 
			g_variant_new_from_data(
				G_VARIANT_TYPE_BYTESTRING, 
				parcel->data(), 
				parcel->dataSize(), 
				TRUE, 
				prvDeleteParcel, 
				parcel));
	}	
	
	// 对象转换
	static Bundle prvToBundle(GVariant* parameters)
	{
		Bundle bundle;
		GVariant* data = nullptr;
		g_variant_get(parameters, "(@ay)", &data);
		
		if (data != nullptr)
		{
			// 反序列化
			Parcel parcel(g_variant_get_data(data), g_variant_get_size(data));
			bundle.readFromParcel(&parcel);
		}
		return bundle;
	}
	
	// ----------------------------------------------------------------------------------------
		
	// 更新给客户端
	static void prvUpdate(Bundle& data)
	{
		std::lock_guard<std::mutex> lock(sMapMutex);
		
		auto it = sIdToConnectionsMap.find(IpcKit::getId(data));
		// 此id有连接
		if (it != sIdToConnectionsMap.end())
		{
			auto& connectionSet = it->second;
			GVariant* variant = prvToGVariant(data);
			for (auto& connection : connectionSet)
			{
				g_variant_ref(variant);
				g_dbus_connection_call(connection,
					NULL, "/com/car/ipc/Channel", "com.car.ipc.Channel", "post",
					variant, NULL,
					G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
			}
			g_variant_unref(variant);
		}
	}
	
	// 更新给客户端
	static void prvUpdate(const void* connection, const std::string& id, int64_t observerId, Bundle& data)
	{
		data.setString(KEY_ID, id);
		data.setInt64(KEY_OBSERVER, observerId);
		
		std::lock_guard<std::mutex> lock(sMapMutex);
		
		GVariant* variant = prvToGVariant(data);
		g_dbus_connection_call((GDBusConnection*)connection,
			NULL, "/com/car/ipc/Channel", "com.car.ipc.Channel", "post",
			variant, NULL,
			G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
	}
	
	// id关联相关 ---------------------------------
	
	// 关联ID
	static void prvAddId(GDBusConnection* connection, const std::string& id)
	{
		std::lock_guard<std::mutex> lock(sMapMutex);
		
		std::set<std::string>& ids = sConnectionToIdsMap[connection];
		// connection不存在,(id也肯定不存在)
		if (ids.empty())
		{
			// 添加connection
			sIdToConnectionsMap[id].insert(connection);
			// 添加id
			ids.insert(id);
		}
		// connection存在, id不存在
		else if (ids.find(id) == ids.end())
		{
			// 添加id
			ids.insert(id);
		}
	}

	// 移除关联
	static void prvRemoveId(GDBusConnection* connection, const std::string& id)
	{
		std::lock_guard<std::mutex> lock(sMapMutex);

		auto idsIt = sConnectionToIdsMap.find(connection);
		// connection存在
		if (idsIt != sConnectionToIdsMap.end())
		{
			auto& idSet = idsIt->second;
			auto idIt = idSet.find(id);
			// id存在, 证明connection和id有关联
			if (idIt != idSet.end())
			{
				// 集合中移除id
				idSet.erase(idIt);
				// 此connection没有关联的任何id
				if (idSet.empty())
				{
					// 移除connection
					sConnectionToIdsMap.erase(idsIt);	
				}
				
				auto connectionsIt = sIdToConnectionsMap.find(id);
				auto& connetionSet = connectionsIt->second;
				// 集合中移除connection
				connetionSet.erase(connection);
				// 此id没有任何关联的connection
				if (connetionSet.empty())
				{
					// 移除id
					sIdToConnectionsMap.erase(connectionsIt);
				}				
			}
		}
	}

	// 清除关联的ID
	static void prvClearIds(GDBusConnection* connection)
	{
		std::lock_guard<std::mutex> lock(sMapMutex);
		
		auto idsIt = sConnectionToIdsMap.find(connection);
		// 此connection有关联的id
		if (idsIt != sConnectionToIdsMap.end())
		{
			auto& idSet = idsIt->second;			
			for (auto& id : idSet)
			{
				auto connectionsIt = sIdToConnectionsMap.find(id);
				auto& connetionSet = connectionsIt->second;
				// 集合中移除connection
				connetionSet.erase(connection);
				// 此id没有任何关联的connection
				if (connetionSet.empty())
				{
					// 移除id
					sIdToConnectionsMap.erase(connectionsIt);
				}
			}
			// 移除connection关联的id集合
			sConnectionToIdsMap.erase(idsIt);
		}
	}
	
	// 回调函数相关 ---------------------------------
	
	IServiceController* prvGetServiceController(const std::string& id)
	{
		IServiceControllerFactory* factory = sFactory;
		while (factory == nullptr)
		{
			std::this_thread::sleep_for(std::chrono::milliseconds(1));
			factory = sFactory;
		}		
		std::string serviceName = IpcKit::getServiceNameFromId(id);
		return factory->getServiceController(serviceName);
	}
	
	static void prvOnPost(Bundle data)
	{
		IServiceController* controller = prvGetServiceController(IpcKit::getId(data));
		if (controller)
		{
			// 转发给IServiceController
			controller->onPost(data);
		}
	}

	static const Bundle prvOnSend(Bundle data)
	{
		IServiceController* controller = prvGetServiceController(IpcKit::getId(data));
		if (controller)
		{
			// 转发给IServiceController
			return controller->onSend(data);
		}
		return Bundle::getEmpty();
	}

	static void prvOnAddId(GDBusConnection* connection, const gchar* _id, gint64 observer)
	{
		// g_print("prvOnAddId %s\n", _id);
		std::string id = _id;
		// 添加connection和id的关联
		prvAddId(connection, id);
		IServiceController* controller = prvGetServiceController(id);
		if (controller)
		{
			// 转发给IServiceController
			controller->handleUpdate(connection, id, observer);
		}
		else
		{
			g_print("controller not found for %s\n", _id);
		}
	}

	static void prvOnRemoveId(GDBusConnection* connection, const gchar* _id)
	{
		std::string id = _id;
		// 取消connection和id的关联
		prvRemoveId(connection, id);

		// TEST 打印
		g_print("\n\t\tON_REMOVE_ID\n");
		g_print("on_remove_id %s\n", _id);
	}
	
	/* 客户端命令的回调 */
	static void prvOnCallback(GDBusConnection* connection,
		const gchar* sender, const gchar* objectPath, const gchar*	interfaceName,
		const gchar* methodName,
		GVariant* parameters, GDBusMethodInvocation* invocation, gpointer user_data)
	{
		// g_print("prvOnCallback %s\n", methodName);
		
		if (g_strcmp0(methodName, "post") == 0) 
		{			
			prvOnPost(prvToBundle(parameters));
			return;
		}

		if (g_strcmp0(methodName, "send") == 0) 
		{
			const Bundle ret = prvOnSend(prvToBundle(parameters));
			// 返回结果给客户端
			g_dbus_method_invocation_return_value(invocation, prvToGVariant(ret));
			return;
		}

		if (g_strcmp0(methodName, "add_id") == 0) 
		{
			// 获取参数
			GVariant* data = NULL;
			gchar* id = NULL;
			guint64 observer = 0;
			g_variant_get(parameters, "(@(sx))", &data);
			g_variant_get(data, "(sx)", &id, &observer);

			if (id != NULL) 
			{
				// 处理参数
				prvOnAddId(connection, id, observer);

				// 释放参数
				g_free(id);
			}
			return;
		}

		if (g_strcmp0(methodName, "remove_id") == 0) 
		{
			// 获取参数
			gchar* id = NULL;
			g_variant_get(parameters, "(s)", &id);

			if (id != NULL) 
			{
				// 处理参数
				prvOnRemoveId(connection, id);

				// 释放参数
				g_free(id);
			}
			return;
		}
	}
	
	// ---------------------------------
	
	// 连接被关闭
	static void prvOnConnectionClosed(GDBusConnection* connection, gboolean remote_peer_vanished, GError* error, gpointer ud)
	{
		// g_print("prvOnConnectionClosed %p\n", connection);

		// 取消所有和connection关联的id和connection的关联
		prvClearIds(connection);

		// 取消引用
		g_object_unref(connection);
	}
		
	// 新连接
	static gboolean prvOnNewConnection(GDBusServer* server, GDBusConnection* connection, gpointer ud)
	{
		// g_print("prvOnNewConnection %p\n", connection);
		
		// 节点信息		
		static const gchar NODE_INFO_XML[] =
			"<node>"
			"  <interface name='com.car.ipc.Channel'>"
			"    <method name='post'>"
			"      <arg type='ay' name='data' direction='in'/>"
			"    </method>"
			"    <method name='send'>"
			"      <arg type='ay' name='data' direction='in'/>"
			"      <arg type='ay' name='ret' direction='out'/>"
			"    </method>"
			"    <method name='add_id'>"
			"      <arg type='(sx)' name='ids' direction='in'/>"
			"    </method>"
			"    <method name='remove_id'>"
			"      <arg type='s' name='id' direction='in'/>"
			"    </method>"
			"  </interface>"
			"</node>";
			
		static GDBusNodeInfo* sNodeInfo = g_dbus_node_info_new_for_xml(NODE_INFO_XML, NULL);
		
		// 接口表
		static const GDBusInterfaceVTable INTERFACE_VTABLE =
		{
			prvOnCallback,
			NULL,
			NULL,
		};

		// 引用
		g_object_ref(connection);

		// 监听断开连接
		g_signal_connect(connection, "closed", G_CALLBACK(prvOnConnectionClosed), NULL);

		// 注册接口虚表
		guint id = g_dbus_connection_register_object(
			connection,
			"/com/car/ipc/Channel",
			sNodeInfo->interfaces[0],
			&INTERFACE_VTABLE,
			NULL, 	/* user_data */
			NULL, 	/* user_data_free_func */
			NULL	/* GError */
		);

		g_assert(id > 0);

		return TRUE;
	}
	
	// 创建服务端
	static void prvNewService(const std::string& serviceName)
	{
		// g_print("prvNewService %s\n", serviceName.c_str());
		
		std::string address = "unix:abstract=";
		address += serviceName;

		// 唯一ID
		gchar* guid = g_dbus_generate_guid();

		// 错误信息
		GError* error = NULL;

		// 创建服务端
		GDBusServer* server = g_dbus_server_new_sync(address.c_str(),
			G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS,
			guid, NULL, NULL, &error);

		// 创建服务端失败
		if (server == NULL) 
		{
			// 打印错误信息
			g_printerr("Error creating server at address %s: %s\n", address.c_str(), error->message);
			g_error_free(error);
		}
		else 
		{
			// 监听连接
			g_signal_connect(server, "new-connection", G_CALLBACK(prvOnNewConnection), NULL);

			// 启动服务
			g_dbus_server_start(server);
		}

		// 释放唯一ID
		g_free(guid);
		
		// TODO. 记录server, 在looper退出时清除
		(void)server;

		//return server;
	}
}	// namespace ipc



